home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1996 April / Software of the Month Club 1996 April.iso / pc / os2 / psutils / src / psspec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-21  |  7.3 KB  |  249 lines

  1. /* psspec.c
  2.  * Copyright (C) Angus J. C. Duggan 1991-1995
  3.  * See file LICENSE for details.
  4.  *
  5.  * page spec routines for page rearrangement
  6.  */
  7.  
  8. #include "psutil.h"
  9. #include "psspec.h"
  10. #include "pserror.h"
  11. #include "patchlev.h"
  12.  
  13. #include <string.h>
  14.  
  15. double width = -1;
  16. double height = -1;
  17.  
  18. /* create a new page spec */
  19. PageSpec *newspec(void)
  20. {
  21.    PageSpec *temp = (PageSpec *)malloc(sizeof(PageSpec));
  22.    if (temp == NULL)
  23.       message(FATAL, "out of memory\n");
  24.    temp->reversed = temp->pageno = temp->flags = temp->rotate = 0;
  25.    temp->scale = 1;
  26.    temp->xoff = temp->yoff = 0;
  27.    temp->next = NULL;
  28.    return (temp);
  29. }
  30.  
  31. /* dimension parsing routines */
  32. int parseint(char **sp, void (*errorfn)(void))
  33. {
  34.    char *s = *sp;
  35.    int num = atoi(s);
  36.  
  37.    while (isdigit(*s))
  38.       s++;
  39.    if (*sp == s) (*errorfn)() ;
  40.    *sp = s;
  41.    return (num);
  42. }
  43.  
  44. double parsedouble(char **sp, void (*errorfn)(void))
  45. {
  46.    char *s = *sp;
  47.    double num = atof(s);
  48.  
  49.    while (isdigit(*s) || *s == '-' || *s == '.')
  50.       s++;
  51.    if (*sp == s) (*errorfn)() ;
  52.    *sp = s;
  53.    return (num);
  54. }
  55.  
  56. double parsedimen(char **sp, void (*errorfn)(void))
  57. {
  58.    double num = parsedouble(sp, errorfn);
  59.    char *s = *sp;
  60.  
  61.    if (strncmp(s, "pt", 2) == 0) {
  62.       s += 2;
  63.    } else if (strncmp(s, "in", 2) == 0) {
  64.       num *= 72;
  65.       s += 2;
  66.    } else if (strncmp(s, "cm", 2) == 0) {
  67.       num *= 28.346456692913385211;
  68.       s += 2;
  69.    } else if (strncmp(s, "mm", 2) == 0) {
  70.       num *= 2.8346456692913385211;
  71.       s += 2;
  72.    } else if (*s == 'w') {
  73.       if (width < 0)
  74.      message(FATAL, "width not initialised\n");
  75.       num *= width;
  76.       s++;
  77.    } else if (*s == 'h') {
  78.       if (height < 0)
  79.      message(FATAL, "height not initialised\n");
  80.       num *= height;
  81.       s++;
  82.    }
  83.    *sp = s;
  84.    return (num);
  85. }
  86.  
  87. double singledimen(char *str, void (*errorfn)(void), void (*usagefn)(void))
  88. {
  89.    double num = parsedimen(&str, errorfn);
  90.    if (*str) (*usagefn)();
  91.    return (num);
  92. }
  93.  
  94. static char *prologue[] = { /* PStoPS procset */
  95. #ifndef SHOWPAGE_LOAD
  96.    "userdict begin",
  97.    "[/showpage/erasepage/copypage]{dup where{pop dup load",    /* prevent */
  98.    " type/operatortype eq{1 array cvx dup 0 3 index cvx put",    /* binding */
  99.    " bind def}{pop}ifelse}{pop}ifelse}forall",            /* in prolog */
  100. #else
  101.    "[/showpage/copypage/erasepage]{dup 10 string cvs dup",
  102.    " length 6 add string dup 0 (PStoPS) putinterval dup",
  103.    " 6 4 -1 roll putinterval 2 copy cvn dup where",
  104.    " {pop pop pop}{exch load def}ifelse cvx cvn 1 array cvx",
  105.    " dup 0 4 -1 roll put def}forall",
  106. #endif
  107.    "[/letter/legal/executivepage/a4/a4small/b5/com10envelope",    /* nullify */
  108.    " /monarchenvelope/c5envelope/dlenvelope/lettersmall/note",    /* paper */
  109.    " /folio/quarto/a5]{dup where{dup wcheck{exch{}put}",    /* operators */
  110.    " {pop{}def}ifelse}{pop}ifelse}forall",
  111.    "/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}",
  112.    " {pop def}ifelse}{def}ifelse",
  113.    "/PStoPSmatrix matrix currentmatrix def",
  114.    "/PStoPSxform matrix def/PStoPSclip{clippath}def",
  115.    "/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def",
  116.    "/initmatrix{matrix defaultmatrix setmatrix}bind def",
  117.    "/initclip[{matrix currentmatrix PStoPSmatrix setmatrix",
  118.    " [{currentpoint}stopped{$error/newerror false put{newpath}}",
  119.    " {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]",
  120.    " {[/newpath cvx{/moveto cvx}{/lineto cvx}",
  121.    " {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}",
  122.    " stopped{$error/errorname get/invalidaccess eq{cleartomark",
  123.    " $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop",
  124.    " /initclip dup load dup type dup/operatortype eq{pop exch pop}",
  125.    " {dup/arraytype eq exch/packedarraytype eq or",
  126.    "  {dup xcheck{exch pop aload pop}{pop cvx}ifelse}",
  127.    "  {pop cvx}ifelse}ifelse",
  128.    " {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def",
  129.    "/initgraphics{initmatrix newpath initclip 1 setlinewidth",
  130.    " 0 setlinecap 0 setlinejoin []0 setdash 0 setgray",
  131.    " 10 setmiterlimit}bind def",
  132.    "end",
  133.    NULL
  134.    };
  135.  
  136. void pstops(int modulo, int pps, int nobind, PageSpec *specs, double draw)
  137. {
  138.    int thispg, maxpage;
  139.    int pageindex = 0;
  140.    char **pro;
  141.  
  142.    scanpages();
  143.  
  144.    maxpage = ((pages+modulo-1)/modulo)*modulo;
  145.  
  146.    /* rearrange pages: doesn't cope properly with loaded definitions */
  147.    writeheader((maxpage/modulo)*pps);
  148. #ifndef SHOWPAGE_LOAD
  149.    writestring("%%BeginProcSet: PStoPS");
  150. #else
  151.    writestring("%%BeginProcSet: PStoPS-spload");
  152. #endif
  153.    if (nobind)
  154.       writestring("-nobind");
  155.    writestring(" 1 15\n");
  156.    for (pro = prologue; *pro; pro++) {
  157.       writestring(*pro);
  158.       writestring("\n");
  159.    }
  160.    if (nobind) /* desperation measures */
  161.       writestring("/bind{}def\n");
  162.    writestring("%%EndProcSet\n");
  163.    /* save transformation from original to current matrix */
  164.    if (writepartprolog()) {
  165.       writestring("userdict/PStoPSxform PStoPSmatrix matrix currentmatrix\n");
  166.       writestring(" matrix invertmatrix matrix concatmatrix\n");
  167.       writestring(" matrix invertmatrix put\n");
  168.    }
  169.    writesetup();
  170.    for (thispg = 0; thispg < maxpage; thispg += modulo) {
  171.       int add_last = 0;
  172.       PageSpec *ps;
  173.       for (ps = specs; ps != NULL; ps = ps->next) {
  174.      int actualpg;
  175.      int add_next = ((ps->flags & ADD_NEXT) != 0);
  176.      if (ps->reversed)
  177.         actualpg = maxpage-thispg-modulo+ps->pageno;
  178.      else
  179.         actualpg = thispg+ps->pageno;
  180.      if (actualpg < pages)
  181.         seekpage(actualpg);
  182.      if (!add_last) {    /* page label contains original pages */
  183.         PageSpec *np = ps;
  184.         char *eob = pagelabel;
  185.         char sep = '(';
  186.         do {
  187.            *eob++ = sep;
  188.            if (np->reversed)
  189.           sprintf(eob, "%d", maxpage-thispg-modulo+np->pageno);
  190.            else
  191.           sprintf(eob, "%d", thispg+np->pageno);
  192.            eob = eob + strlen(eob);
  193.            sep = ',';
  194.         } while ((np->flags & ADD_NEXT) && (np = np->next));
  195.         strcpy(eob, ")");
  196.         writepageheader(pagelabel, ++pageindex);
  197.      }
  198.      writestring("userdict/PStoPSsaved save put\n");
  199.      if (ps->flags & GSAVE) {
  200.         char buffer[BUFSIZ];
  201.         writestring("PStoPSmatrix setmatrix\n");
  202.         if (ps->flags & OFFSET) {
  203.            sprintf(buffer, "%f %f translate\n", ps->xoff, ps->yoff);
  204.            writestring(buffer);
  205.         }
  206.         if (ps->flags & ROTATE) {
  207.            sprintf(buffer, "%d rotate\n", ps->rotate);
  208.            writestring(buffer);
  209.         }
  210.         if (ps->flags & SCALE) {
  211.            sprintf(buffer, "%f dup scale\n", ps->scale);
  212.            writestring(buffer);
  213.         }
  214.         writestring("userdict/PStoPSmatrix matrix currentmatrix put\n");
  215.         if (width > 0 && height > 0) {
  216.            char buffer[BUFSIZ];
  217.            writestring("userdict/PStoPSclip{0 0 moveto\n");
  218.            sprintf(buffer, " %f 0 rlineto 0 %f rlineto -%f 0 rlineto\n",
  219.                width, height, width);
  220.            writestring(buffer);
  221.            writestring(" closepath}put initclip\n");
  222.            if (draw > 0) {
  223.           sprintf(buffer, "gsave clippath 0 setgray %f setlinewidth stroke grestore\n", draw);
  224.           writestring(buffer);
  225.            }
  226.         }
  227.      }
  228.      if (add_next) {
  229. #ifndef SHOWPAGE_LOAD
  230.         writestring("/showpage{}def/copypage{}def/erasepage{}def\n");
  231. #else
  232.         writestring("/PStoPSshowpage{}store/PStoPScopypage{}store/PStoPSerasepage{}store\n");
  233. #endif
  234.      }
  235.      if (actualpg < pages) {
  236.         writepagesetup();
  237.         writestring("PStoPSxform concat\n");
  238.         writepagebody(actualpg);
  239.      } else {
  240.         writestring("PStoPSxform concat\n");
  241.         writestring("showpage\n");
  242.      }
  243.      writestring("PStoPSsaved restore\n");
  244.      add_last = add_next;
  245.       }
  246.    }
  247.    writetrailer();
  248. }
  249.